package com.ironone.streaming.mediaplayer;

import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import com.ironone.streaming.application.FormObject;
import android.media.AudioManager;
import android.media.MediaPlayer;

public class MyMediaPlayer {
        private static MediaPlayer mediaPlayer = null;

        private static int iVolume;
        private final static int INT_VOLUME_MAX = 100;
        private final static int INT_VOLUME_MIN = 0;
        private final static float FLOAT_VOLUME_MAX = 1;
        private final static float FLOAT_VOLUME_MIN = 0;
        private final static int FADE_DURATION = 500; // In milliseconds. Can't be 0

        private static MediaPlayerStatus mediaPlayerStatus = MediaPlayerStatus.RELEASED;
        private static boolean isPlayerOnBackground = false;
        private static boolean isHdOn = true;
        private static boolean isPauseBtnClicked = true;

        public static String SVC_NOTIFICATION = "com.ironone.SERVICE_CALLBACK";   //Activity sending notifications to service
        public static String ACT_NOTIFICATION = "com.ironone.ACTIVITY_CALLBACK";  //Service sending notifications to activity
        public static String VALUE = "value";

        private MyMediaPlayer(){
        }

        public static MediaPlayer getMediaPlayerInstance(){
                if (mediaPlayer == null) {
                        mediaPlayer = new MediaPlayer();
                }
                return mediaPlayer;
        }

        public static MediaPlayerStatus getMediaPlayerStatus(){
                return mediaPlayerStatus;
        }

        public static void setMediaPlayerStatus(MediaPlayerStatus status){
                mediaPlayerStatus = status;
        }

        public static boolean isPlaying(){
                try {
                        if(mediaPlayer == null) return false;
                        return mediaPlayer.isPlaying();
                } catch (Exception e) {
                        return false;
                }
        }

        public static boolean getIsPlayerOnBackground(){
                return isPlayerOnBackground;
        }

        public static void setIsPlayerOnBackground(boolean x){
                isPlayerOnBackground = x;
        }

        public static boolean getIsHDOn(){
                return isHdOn;
        }

        public static void setIsHDOn(boolean y){
                isHdOn = y;
        }

        public static boolean getMediaPlayerPauseClicked() {
                return isPauseBtnClicked;
        }

        public static void setMediaPlayerPauseClicked(boolean pStatus) {
                isPauseBtnClicked = pStatus;
        }


        public static void prepareMediaPlayer() throws Exception{
                try {
                        getMediaPlayerInstance();
                        mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                        
                        if(getIsHDOn())
                                mediaPlayer.setDataSource(FormObject.getInstance().getHDStream());
                        else
                                mediaPlayer.setDataSource(FormObject.getInstance().getSDStream());  //FormObject.getInstance().getSDStream()

                        if(!MyMediaPlayer.getMediaPlayerPauseClicked()){   //TODO: check this
                                mediaPlayerStatus = MediaPlayerStatus.PREPARING;
                                mediaPlayer.prepareAsync();
                        }
                }  catch (IllegalArgumentException e) {
                    throw e;
                } catch (SecurityException e) {
                    throw e;
                } catch (IllegalStateException e) {
                    throw e;
                } catch (IOException e) {
                    throw e;
                }
        }

        public static void playMediaPlayer(){
                try {
                        if (!isPauseBtnClicked) {
                                incVolume(FADE_DURATION);
                                mediaPlayer.start();
                                mediaPlayerStatus = MediaPlayerStatus.PLAYING;
        						//playbtn_loadingcircle.setVisibility(View.VISIBLE);
                        }               

                        /*try {
                                wifiLock.acquire();
                        } catch (Exception e) {
                                e.printStackTrace();
                        }*/

                } catch (Exception e) {
                        releaseMediaPlayer();                   
                }
        }

        public static void pauseMediaPlayer(){
                try {
                        decVolumeAndProceed(FADE_DURATION, MediaPlayerStatus.PAUSED);
                } catch (Exception e) {
                        // TODO Auto-generated catch block
                }

                //mediaPlayerStatus = MediaPlayerStatus.paused;

                /*try {
                        wifiLock.release();
                } catch (Exception e) {
                        e.printStackTrace();
                }*/
        }

        public static void resetMediaPlayer(){
                try {
                        if (mediaPlayer != null)
                                decVolumeAndProceed(FADE_DURATION, MediaPlayerStatus.RESETED);

                        /*try {
                                wifiLock.release();
                        } catch (Exception e) {
                                e.printStackTrace();
                        }*/
                } catch (Exception e) {
                        // TODO Auto-generated catch block
                }
        }

        public static void releaseMediaPlayer(){
                try {
                        if (mediaPlayer != null) {
                                decVolumeAndProceed(FADE_DURATION, MediaPlayerStatus.RESETED);

                                /*try {
                                        wifiLock.release();
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }*/
                        }
                } catch (Exception e) {
                        // TODO Auto-generated catch block
                }
        }

        public static void resetAndPrepareMediaPlayer() throws Exception{
                try {
                        decVolumeAndProceed(FADE_DURATION, MediaPlayerStatus.RESET_N_PREPARE);

                        /*try {
                                wifiLock.release();
                        } catch (Exception e) {
                                e.printStackTrace();
                        }*/
                } catch (Exception e) {
                        throw e;
                }
        }


        //Start increasing volume in increments
        private static void incVolume(int fadeDuration){
                try {
                        if(fadeDuration == 0)
                                fadeDuration = 1;

                        //Set current volume, depending on fade or not
                        if (fadeDuration > 0) 
                                iVolume = INT_VOLUME_MIN;
                        else 
                                iVolume = INT_VOLUME_MAX;

                        updateVolume(0);

                        //Start increasing volume in increments
                        if(fadeDuration > 0)
                        {
                                final Timer timer = new Timer(true);
                                TimerTask timerTask = new TimerTask() 
                                {
                                        @Override
                                        public void run() 
                                        {
                                                updateVolume(1);
                                                if (iVolume == INT_VOLUME_MAX)
                                                {
                                                        timer.cancel();
                                                        timer.purge();
                                                }
                                        }
                                };

                                // calculate delay, cannot be zero, set to 1 if zero
                                int delay = fadeDuration/INT_VOLUME_MAX;
                                if (delay == 0) delay = 1;
                                timer.schedule(timerTask, delay, delay);
                        }
                } catch (Exception e) {
                        // TODO Auto-generated catch block
                }
        }

        static boolean result = false;
        private static void decVolumeAndProceed(int fadeDuration, final MediaPlayerStatus playerStatus) throws Exception{
                try {
                        if(fadeDuration == 0)
                                fadeDuration = 1;

                        //Set current volume, depending on fade or not
                        if (fadeDuration > 0)
                                iVolume = INT_VOLUME_MAX;
                        else
                                iVolume = INT_VOLUME_MIN;

                        updateVolume(0);

                        //Start increasing volume in increments
                        if(fadeDuration > 0) {
                                final Timer timer = new Timer(true);
                                TimerTask timerTask = new TimerTask() {
                                        @Override
                                        public void run() {   
                                                updateVolume(-1);
                                                if (iVolume == INT_VOLUME_MIN) {
                                                        switch (playerStatus.ordinal()) {
                                                        case 0: //MediaPlayerStatus.playing
                                                                break;

                                                        case 1: //MediaPlayerStatus.paused
                                                                if (mediaPlayer.isPlaying()){ 
                                                                        mediaPlayer.pause();
                                                                        mediaPlayerStatus = MediaPlayerStatus.PAUSED;
                                                                }
                                                                break;

                                                        case 2: //MediaPlayerStatus.buffering
                                                                break;

                                                        case 3: //MediaPlayerStatus.released
                                                                if(mediaPlayer.isPlaying()) {
                                                                        mediaPlayer.stop();                             
                                                                }
                                                                mediaPlayer.release();
                                                                mediaPlayer = null;
                                                                mediaPlayerStatus = MediaPlayerStatus.RELEASED;

                                                                break;

                                                        case 4: //MediaPlayerStatus.reseted
                                                                if(mediaPlayer.isPlaying()) {
                                                                        mediaPlayer.stop();                             
                                                                }
                                                                mediaPlayer.reset();
                                                                mediaPlayerStatus = MediaPlayerStatus.RESETED;
                                                                break;

                                                        case 5: //MediaPlayerStatus.forcePaused
                                                                break;

                                                        case 6: //MediaPlayerStatus.resetAndPrepare  RESET_N_PREPARE
                                                                if(mediaPlayer.isPlaying()) {
                                                                        mediaPlayer.stop();
                                                                }
                                                                mediaPlayer.reset();
                                                                mediaPlayerStatus = MediaPlayerStatus.RESETED;
                                                                
                                                                try {
                                                                        prepareMediaPlayer();
                                                                } catch (Exception e) {
                                                                        result = true;
                                                                }                                                               
                                                                break;

                                                        default:
                                                                break;
                                                        }

                                                        timer.cancel();
                                                        timer.purge();
                                                }
                                        }
                                };

                                // calculate delay, cannot be zero, set to 1 if zero
                                int delay = fadeDuration/INT_VOLUME_MAX;
                                if (delay == 0) delay = 1;
                                timer.schedule(timerTask, delay, delay);
                        }                                               
                } catch (Exception e) {
                        throw e;
                }
        }

        private static void updateVolume(int change){
                try {
                        //increment or decrement depending on type of fade
                        iVolume = iVolume + change;

                        //ensure iVolume within boundaries
                        if (iVolume < INT_VOLUME_MIN)
                                iVolume = INT_VOLUME_MIN;
                        else if (iVolume > INT_VOLUME_MAX)
                                iVolume = INT_VOLUME_MAX;

                        //convert to float value
                        float fVolume = 1 - ((float) Math.log(INT_VOLUME_MAX - iVolume) / (float) Math.log(INT_VOLUME_MAX));

                        //ensure fVolume within boundaries
                        if (fVolume < FLOAT_VOLUME_MIN)
                                fVolume = FLOAT_VOLUME_MIN;
                        else if (fVolume > FLOAT_VOLUME_MAX)
                                fVolume = FLOAT_VOLUME_MAX;     

                        mediaPlayer.setVolume(fVolume, fVolume);
                } catch (Exception e) {
                        // TODO Auto-generated catch block
                }
        }
}